iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 11
0
Blockchain

區塊鏈開發(Blockchain/DLT Application Development)系列 第 11

以太坊(Ethereum):Web3.js

  • 分享至 

  • xImage
  •  

Web3.js 提供了以太坊的 Client 元件,用以跟智能合約(Smart Contract)溝通,是一個 Node.js 插件。

於 Node.js 中使用以下指令安裝。

npm install web3

Web3.jx

Web3 提供了以下功能:

  • 合約部署
  • 交易物件 (Transaction Object)
  • Reflection (反映) 方法:ABI
  • 呼叫合約方法 (Contract Functions):Call、Transaction
  • 監聽事件:過濾事件、全域事件

通訊協定

以太坊提供 3 種通訊方式。
Web3 是採用 RPC 通訊,雖相較之下安全性較低,但開發上較有彈性且容易上手。

  • RPC :較彈性 - Web3.js
  • IPC :較快且安全 - geth attach
  • WebSocket:適合高頻交易處理,適合實作網頁即時服務用

交易 & 區塊

將交易資訊傳送給智能合約後,會非同步的接收其交易處理狀態,可做對應處理:

  • pending transactions
    • 本地 enode 中還沒被放進 pending block 來 mining  的交易
  • pending block
    • 本地 enode 正在 mining 的 block
  • latest block
    • chain 上最新的 block
  • transactionReceipt
    • 指 transaction 執行過後 在 chain 中 的記錄

Application Blockchain Interface, ABI

客戶端提供了多種 API,以下簡述一下必要以及使用度較高的物件:

  • eth
    • 用來透過 Enode 向 Ethereum 鏈操作、感知 Ethereum 鏈上發生的事情
  • admin
    • 管理 Enode 的元件服務
  • miner
    • 管理挖礦元件
  • personal
    • 管理帳戶:解鎖、鎖定帳戶,及以指定帳戶的名義簽署交易

事件監聽

設定物件

var block = eth.filter(
'latest’
,{
    from:Number | String
    ,to:Number | String
    ,address: String
});

開始/停止

block.watch(function(err, latestBlockHash) {});
block.stopWatching();

物件操作

//block
eth.getBlock('pending’);
eth.getBlock(NUM);

//transaction
eth.getTransaction(HASH);
eth.getTransactionReceipt(HASH);
eth.pendingTransactions;

//address
eth.getBalance(addressString); 

//enode
eth.accounts;
eth.coinbase == eth.accounts[0];	//挖擴者

//web3
web3.fromWei;
web3.toWei;

//minter
miner.start(N);
miner.stop();取得
eth.mining;
eth.syncing;

惰性節點。
這是一個簡單的範例,其中只有挖擴的動作,沒有交易行為。

function work() 
{
	if (eth.getBlock("pending").transactions.length > 0) 
	{
        if (eth.mining)
		{
			return;
		}
        
        miner.start(threads);
    } 
	else 
	{
        miner.stop();
    }
}

var threads = 1

eth.filter("latest", function(err, block) {work(); });
eth.filter("pending", function(e rr, block) {work(); });

work();

開發與部屬

建立 web3 物件

// 8545 是預設的通訊埠
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

建立合約

推薦使用 browser-solidity 自動產生的 web3 deploy code。
編譯後,可以得到 bytecode 及 ABI。

//經由 sendTransaction 搭上 data (bytecode) 
eth.sendTransaction
({
    from: eth.coinbase
    ,data: BYTECODE
    ,gas: 1234567
});
eth.getTransactionReceipt(TxHash).contractAddress;

部屬合約

var ABI = 
[{
    "constant":true
    ,"inputs":[]
    ,"name":"getData"
    ,"outputs":[{"name":"","type":"string"}]
    ,"payable":false
    ,"type":"function"
}
,{
    "constant":false
    ,"inputs":[{"name":"input","type":"string"}]
    ,"name":"setData"
    ,"outputs":[]
    ,"payable":false
    ,"type":"function"
}];

var contract = eth.conract(ABI).at("0xa5a28cbaa3d7a37394260c9f7029f5b67bea913c");

Transaction vs Call

建立交易

//登入帳戶
personal.unlockAccount('帳戶位址', '密碼', 幾秒);

//交易物件
eth.sendTransaction
({
	from: 		//從什麼帳戶位址
	,to:		//從什麼帳戶位址,假如要部署合約可以忽略
	,gas:		//多少 wei,預設 90000 沒用完的會退回來 
	,gasPrice:	//多少 gas,gas 單價,Enode設定
	,value:		//多少 wei 要傳 	
	,data: 		//附加資料:部署合約或呼叫合約,或也可以儲存資料,最大值為 89kb 
	,nonce:		//用於標示 Transaction 的順序,所以可以以相同的 nonce 覆蓋同 nonce 的交易
});

呼叫合約

  • Transaction

    //TxHash:回傳值,後續用來追蹤區塊 Block
    storageContract.setData("區塊鏈!"
    ,{
        from: eth.coinbase
        ,gas: 1234567
    });
    
    //真實使用的gas值,可用來判斷是否執行成功
    eth.getTransactionReceipt(TxHash).gasUsed();
    
  • Call

    var data = storageContract.getData();
    storageContract.getData(function(err, data) 
    {
        console.log(err, data);
    });
    
  • Transaction

    • 被 mine
    • 花到錢
    • 會影響資料庫 (Blockchain)
  • Call

    • 不會被 mine
    • 不會花到錢
    • 不會影響資料庫

整合範例

Solidity

  • contract
    pragma solidity ^0.4.2;
    
    contract event 
    {
        string public data;
    
        event transaction(string input, address from, uint time);
    
        function call() constant returns(string) {return data;}
    
        function transaction(string input) 
        {
            data = input;
            transaction(input, msg.sender, now);
        }
    }
    
  • event
    contract event
    {
        event fire(address indexed sender, uint indexed value); 
        function fire() 
        {
            fire(msg.sender, msg.value);
        }
    }
    

Web3.js

  • Transaction
    //
    var watcher = contract.fire({},{from:?, to:?});
    watcher.get(function(err, eventLog) 
    {
        console.log(JSON.stringify(eventLog, null, 2));
    });
    //indexed
    var watcher = contract.fire({num: 1});
    watcher.watch(function(e, r){console.log('1')});
    watcher.stopWatching();
    
  • Call
    contract.fire({}, function(err, eventLog) 
    {
        console.log(JSON.stringify(eventLog, null, 2));
    });
    

常見漏洞

Solidity 其語法類似於 JavaScript,開發時須注意的安全性事項,也有類似特性:

  • Reflection:反射,有可能會造成回呼,形成邏輯漏洞
  • 堆疊深度(Call stack Depth):目前最深深度為 1024
  • 溢位:因重要的數字記得檢查溢位檢查

上一篇
以太坊(Ethereum):智能合約
下一篇
Hyperledger Fabric
系列文
區塊鏈開發(Blockchain/DLT Application Development)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言